package cate.game.role.res.treasureturntable;

import cate.common.table.d.GDObj;
import cate.common.table.d.GDTreasureTurntable;
import cate.common.table.res.treasureturntable.row.TreasureTurntableBaseRow;
import cate.common.table.res.treasureturntable.row.TreasureTurntableGroupRow;
import cate.common.table.res.treasureturntable.row.TreasureTurntableLuckyRow;
import cate.common.util.GameResult;
import cate.common.util.random.RWList;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.MixResConsumer;
import cate.game.res.MixResItem;
import cate.game.res.drop.DropConfigHelper;
import cate.game.res.treasureturntable.TreasureTurntableLog;
import cate.game.res.treasureturntable.TreasureTurntableLogDetail;
import cate.game.role.Role;
import cate.game.role.mall.refresh.FreeRefresh;
import cate.game.role.res.treasureturntable.msg.TreasureTurntableDrawResp;
import cate.game.role.res.treasureturntable.msg.TreasureTurntableSingleDataResp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@NoteClass("单个转盘数据")
public class SingleTreasureTurntable extends FreeRefresh {
    @NoteField("转盘类型")
    public byte type;

    @NoteField("积分")
    public int score;

    @NoteField("奖励")
    public Map<Byte, TreasureTurnTableItem> rewardMap;

    @NoteField("个人抽奖记录")
    public TreasureTurntableLog selfLog;

    @NoteField("积分奖励领取记录")
    public Map<Integer, Boolean> scoreRewardMap;

    public SingleTreasureTurntable() {

    }

    public SingleTreasureTurntable(byte type, int turntableId) {
        this.type = type;
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (rewardMap == null) {
            rewardMap = new HashMap<>();
        }
        if (selfLog == null) {
            selfLog = new TreasureTurntableLog();
        }
        if (scoreRewardMap == null) {
            scoreRewardMap = new HashMap<>();
        }
        selfLog.initialize();
        checkRefreshTime();
    }

    public TreasureTurntableLog getZoneLog() {
        return role.getGame().res.treasureTurntable.getLog(type);
    }

    @Override
    public void checkRefreshTime() {
        super.checkFreeCycle();
    }

    /**
     * 刷新轮盘
     */
    public void refreshItems() {
        TreasureTurntableBaseRow baseRow = getNewBase();
        if (baseRow != null) {
            rewardMap.clear();
            List<TreasureTurntableGroupRow> groupRows = role.getGame().table.treasureTurntable.group.getGroupRows(baseRow.group);
            for (TreasureTurntableGroupRow row : groupRows) {
                MixRes reward = DropConfigHelper.getDropReward(role.getGame(), row.dropId);
                TreasureTurnTableItem item = new TreasureTurnTableItem(row.pos, reward, row.id);
                rewardMap.put(row.pos, item);
            }
        }
    }

    @JsonIgnore
    private List<TreasureTurntableGroupRow> getGroupRows() {
        TreasureTurntableBaseRow baseRow = getNewBase();
        if (baseRow == null) {
            return Collections.emptyList();
        }
        return role.getGame().table.treasureTurntable.group.getGroupRows(baseRow.group);
    }

    @JsonIgnore
    private TreasureTurntableBaseRow getNewBase() {
        return role.getGame().table.treasureTurntable.base.getRow(type, role.getBase().level);
    }

    @Override
    @JsonIgnore
    public String getFreeCycle() {
        TreasureTurntableBaseRow base = getNewBase();
        if (base == null) {
            return "";
        }
        return base.freeCycle;
    }

    @Override
    public int getFreeTimeMax() {
        return 1;
    }

    /**
     * 跨天刷新
     */
    @Override
    public void onDaySpan(boolean silence) {
        refreshItems();
    }

    /**
     * 抽奖
     */
    public GameResult<Void> drawItems(byte drawType) {
        GameResult<Void> r = new GameResult<>();
        TreasureTurntableBaseRow baseRow = getNewBase();
        if (baseRow == null) {
            return r.fail("当前无法抽奖，请刷新");
        }
        MixRes consume = new MixRes();
        if (drawType == GDTreasureTurntable.SINGLE_DRAW) {
            consume.addList(new MixRes(baseRow.singleConsumeStr));
        } else if (role.getBase().vip >= baseRow.vipLimit){
            consume.addList(new MixRes(baseRow.vipMultiConsumeStr));
        } else {
            consume.addList(new MixRes(baseRow.generalMultiConsumeStr));
        }
        return new MixResConsumer<Void>()
                .res(consume)
                .tips(true)
                .success(e -> {
                    byte lastPos = 1;
                    int drawTimes = drawType == GDTreasureTurntable.SINGLE_DRAW ? 1 : 15;
                    MixRes reward = new MixRes(baseRow.scoreStr).multiply(drawTimes);
                    for (int i = 0; i < drawTimes; ++i) {
                        TreasureTurnTableItem item = draw();
                        addToLog(item);
                        lastPos = item.pos;
                        reward.addList(item.reward);
                    }
                    score += drawTimes * baseRow.score;
                    new MixResAdder()
                            .setSendMailWhenFull(true)
                            .setRes(reward)
                            .exe(role);
                    role.sendNow(new TreasureTurntableDrawResp(reward, lastPos));
                    noticeUpdate();
                    role.getHistory().action.advanceTurntableTimes(type, drawTimes);
                    return null;
                })
                .exe(role);
    }

    private void addToLog(TreasureTurnTableItem item) {
        TreasureTurntableLogDetail logDetail = new TreasureTurntableLogDetail(role.getBase().name, item.reward);
        addSelfLog(logDetail);
        if (item.isUnique(role.getGame())) {
            role.getGame().res.treasureTurntable.addLog(type, logDetail);
        }
    }

    private void addSelfLog(TreasureTurntableLogDetail logDetail) {
        selfLog.addLog(logDetail, GDTreasureTurntable.LOG_SIZE);
    }

    private TreasureTurnTableItem draw() {
        RWList<TreasureTurntableGroupRow> rwl = new RWList<>();
        getGroupRows()
                .stream()
                .filter(a -> !a.isUnique || !rewardMap.get(a.pos).hasDraw)
                .forEach(rwl::add);
        rwl.setup();
        TreasureTurnTableItem item = rewardMap.get(rwl.get().pos);
        item.hasDraw = true;
        return item;
    }

    public GameResult<Void> refresh(boolean needRefresh) {
        GameResult<Void> r = new GameResult<>();
        TreasureTurntableBaseRow baseRow = getNewBase();
        if (baseRow == null) {
            return r.fail("转盘不存在");
        }
        checkRefreshTime();
        if (needRefresh) {
            if (hasFreeTimes()) {
                costFreeTimes();
            } else {
                GameResult<MixResItem> consumeRes = new MixRes(GDObj.getMixResStr(GDObj.Type.NUM, GDObj.Num.M1, baseRow.refreshConsumeNum)).consume(role, null);
                if (!consumeRes.ok()) {
                    role.getGame().notice.tipResItem(role, consumeRes.data);
                    return r.fail(consumeRes);
                }
            }
            refreshItems();
        }
        noticeUpdate();
        return r;
    }

    @JsonIgnore
    public GameResult<Void> getScoreReward(int rewardId) {
        GameResult<Void> r = new GameResult<>();
        if (scoreRewardMap.containsKey(rewardId)) {
            return r.fail("奖励已领取");
        }
        List<TreasureTurntableLuckyRow> rows = role.getGame().table.treasureTurntable.lucky.getTypeRows(type);
        if (rows.isEmpty()) {
            return r.fail("奖励不存在");
        }
        int maxScore = 0;
        TreasureTurntableLuckyRow rewardRow = null;
        for (TreasureTurntableLuckyRow row : rows) {
            if (row.id == rewardId) {
                rewardRow = row;
            }
            maxScore = Math.max(maxScore, row.value);
        }
        if (rewardRow == null) {
            return r.fail("奖励不存在");
        }
        if (score < rewardRow.value) {
            return r.fail("未达到奖励领取条件");
        }
        scoreRewardMap.put(rewardId, true);
        if (scoreRewardMap.size() == rows.size()) {
            score -= maxScore;
            scoreRewardMap.clear();
        }
        new MixResAdder()
                .setSendMailWhenFull(true)
                .setDialogReward(true)
                .setRes(new MixRes(rewardRow.rewardStr))
                .exe(role);
        noticeUpdate();
        return r;
    }

    public void noticeUpdate() {
        role.sendNow(new TreasureTurntableSingleDataResp(this));
    }
}
